home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / technical documentation / develop / develop issue 25 / develop issue 25 code / toolfrontend.sea / ToolFrontEnd / ToolFrontEnd Source / ToolFrontEnd Compiler / ToolFrontEnd.c / ToolFrontEnd.c
Encoding:
C/C++ Source or Header  |  1996-02-29  |  11.7 KB  |  469 lines  |  [TEXT/CWIE]

  1.  
  2. /* standard headers */
  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6.  
  7. /* system headers */
  8. #include <Gestalt.h>
  9. #include <LowMem.h>
  10. #include <Strings.h>
  11. #include <TextUtils.h>
  12. #include <CodeFragments.h>
  13. #include <Resources.h>
  14. #include <MixedMode.h>
  15.  
  16. /* compiler headers */
  17. #include <A4Stuff.h>
  18. #include <DropInCompiler.h>
  19.  
  20. /* project headers */
  21. #include "ToolFrontEnd.h"
  22. #include "ToolServer.h"
  23. #include "FullPath.h"
  24.  
  25.  
  26.  
  27. /* prototypes of local functions */
  28. static OSErr    Compile(ToolFrontEndStatus* status);
  29. static OSErr    ProcessFile(ToolFrontEndStatus* status, ToolFrontEndPref **prefs,
  30.                             short currentExtension);
  31.  
  32.  
  33. // mixed mode info for include file scanners
  34. enum
  35. {
  36.     uppScannerEntryPointInfo = kPascalStackBased
  37.          | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  38.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ToolFrontEndStatus*)))
  39. };
  40.  
  41.  
  42. /*
  43.  *    main    -    main entry-point for ToolFrontEnd Tool
  44.  *
  45.  */
  46.  
  47. pascal short main(CompilerParameterBlockPtr cpb)
  48. {
  49.     short                    result;
  50.     ToolFrontEndStatus*        status;
  51.     OSErr                    err;
  52.     
  53.     /* set up global world (68K only) */
  54.     EnterCodeResource();
  55.     
  56.     result = noErr;
  57.     
  58.     /* dispatch on compiler request */
  59.     switch (cpb->request)
  60.     {
  61.     case reqInitCompiler:
  62.         /* compiler has just been loaded into memory */
  63.         break;
  64.         
  65.     case reqTermCompiler:
  66.         /* compiler is about to be unloaded from memory */
  67.         break;
  68.         
  69.     case reqCompile:
  70.         /* compile a source file */
  71.         status = (ToolFrontEndStatus*)NewPtrClear(sizeof(ToolFrontEndStatus));
  72.         err = MemError();
  73.         if (err == noErr)
  74.         {
  75.             int i;
  76.             status->cpb = cpb;
  77.             err = Compile(status);
  78.             for (i = 0; i < status->numFolderPaths; i++)
  79.                 DisposeHandle(status->folderPaths[i].path);
  80.             DisposePtr((Ptr)status);
  81.         }
  82.         result = (err == noErr);
  83.         break;
  84.         
  85.     default:
  86.         result = paramErr;
  87.         break;
  88.     }
  89.     
  90.     /* tear down global world (68K only) */
  91.     ExitCodeResource();
  92.     
  93.     /* return result code */
  94.     return (result);
  95. }
  96.  
  97.  
  98. static OSErr    Compile(ToolFrontEndStatus* status)
  99. {
  100.     Handle                prefsHand;
  101.     ToolFrontEndPref**    prefs;
  102.     OSErr                err;
  103.     short                currentExtension;
  104.     
  105.     /* Load in our prefs. */
  106.     err = CWCompGetPreferences(status->cpb, kToolFrontEndPanelName, &prefsHand);
  107.     if (err != noErr) return err;
  108.     prefs = (ToolFrontEndPrefHandle)prefsHand;
  109.     
  110.     status->linecount = 0;
  111.     
  112.     // find the extension of this file
  113.     {
  114.         Str15 extension;
  115.         int i;
  116.         Byte state;
  117.         
  118.         for (i = status->cpb->sourcefile.name[0]; i > 0 && status->cpb->sourcefile.name[i] != '.'; i--)
  119.             ;
  120.         if (i < 0) return paramErr;
  121.         extension[0] = status->cpb->sourcefile.name[0] - (i - 1);
  122.         BlockMoveData(status->cpb->sourcefile.name + i, extension + 1, extension[0]);
  123.         
  124.         state = HGetState((Handle)prefs);
  125.         HLock((Handle)prefs);
  126.         for (i = 0, currentExtension = -1; i < (*prefs)->numExtensions; i++)
  127.         {
  128.             if (EqualString(extension, (*prefs)->extensions[i].extension, false, true))
  129.             {
  130.                 currentExtension = i;
  131.                 break;
  132.             }
  133.         }
  134.         HSetState((Handle)prefs, state);
  135.         if (currentExtension == -1) return paramErr;
  136.     }
  137.     
  138.     // process include files
  139.     if ((*prefs)->extensions[currentExtension].scanner[0] != 0)
  140.     {
  141.         err = ProcessFile(status, prefs, currentExtension);
  142.     }
  143.     
  144.     // now build the ToolServer command
  145.     {
  146.         Handle commandHandle = NewHandle(0);
  147.         AEDesc command;
  148.         CStringHandle output = NULL, diagnostic = NULL;
  149.         Str31 nameStem;
  150.         
  151.         // parameterize the ToolServer command line
  152.         
  153.         if (status->numFolderPaths > 0)
  154.         {
  155.             // add the IncludeFiles variable
  156.             int i;
  157.  
  158.             PtrAndHand("Set IncludeFiles \'", commandHandle, sizeof("Set IncludeFiles \'") - 1);
  159.             for (i = 0; i < status->numFolderPaths; i++)
  160.             {
  161.                 char space = ' ', quote = '\"';
  162.                 Byte state;
  163.                 
  164.                 state = HGetState((Handle)prefs);
  165.                 HLock((Handle)prefs);
  166.                 PtrAndHand((*prefs)->extensions[currentExtension].includeFileArg + 1,
  167.                             commandHandle, (*prefs)->extensions[currentExtension].includeFileArg[0]);
  168.                 HSetState((Handle)prefs, state);
  169.                 PtrAndHand(&space, commandHandle, 1);
  170.                 PtrAndHand("e, commandHandle, 1);
  171.                 HandAndHand(status->folderPaths[i].path, commandHandle);
  172.                 PtrAndHand("e, commandHandle, 1);
  173.                 PtrAndHand(&space, commandHandle, 1);
  174.             }
  175.             PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  176.         }
  177.         
  178.         // add the SourceFile variable -- XXX -- if not saved, use temp file instead!
  179.         {
  180.             Handle fileName;
  181.             short fileNameSize;
  182.             
  183.             PtrAndHand("Set SourceFile \'", commandHandle, sizeof("Set SourceFile \'") - 1);
  184.             err = FSpGetFullPath(&status->cpb->sourcefile, &fileNameSize, &fileName);
  185.             if (err == noErr)
  186.             {
  187.                 HandAndHand(fileName, commandHandle);
  188.                 DisposeHandle(fileName);
  189.                 PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  190.             }
  191.         }
  192.     
  193.         // add the SourceFileStem variable
  194.         if (err == noErr)
  195.         {
  196.             int i;
  197.             
  198.             BlockMoveData(status->cpb->sourcefile.name, nameStem, status->cpb->sourcefile.name[0] + 1);
  199.             for (i = nameStem[0]; i > 0; i--)
  200.             {
  201.                 if (nameStem[i] == '.')
  202.                 {
  203.                     nameStem[0] = i - 1;
  204.                     break;
  205.                 }
  206.             }
  207.             
  208.             PtrAndHand("Set SourceFileStem \'", commandHandle, sizeof("Set SourceFileStem \'") - 1);
  209.             PtrAndHand(nameStem + 1, commandHandle, nameStem[0]);
  210.             PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  211.         }
  212.         
  213.         // add the Directory command to go to the project folder
  214.         if (err == noErr)
  215.         {
  216.             short dirNameLength;
  217.             Handle dirName;
  218.             
  219.             err = GetFullPath(status->cpb->targetfile.vRefNum, status->cpb->targetfile.parID, NULL, &dirNameLength, &dirName);
  220.             
  221.             if (err == noErr)
  222.             {
  223.                 PtrAndHand("Directory \'", commandHandle, sizeof("Directory \'") - 1);
  224.                 HandAndHand(dirName, commandHandle);
  225.                 PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  226.                 DisposeHandle(dirName);
  227.             }
  228.         }
  229.         
  230.         // add the Execute command for the script include file, if any
  231.         if ((err == noErr) && (*prefs)->scriptIncludeFile[0] != 0)
  232.         {
  233.             Str31 includeFileName;
  234.             FSSpec includeSpec;
  235.             Boolean alreadyincluded;
  236.             Handle hand = NULL;
  237.             long size;
  238.             
  239.             Byte state = HGetState((Handle)prefs);
  240.             HLock((Handle)prefs);
  241.             BlockMoveData((*prefs)->scriptIncludeFile, includeFileName,
  242.                           (*prefs)->scriptIncludeFile[0] + 1);
  243.             HSetState((Handle)prefs, state);
  244.             
  245.             err = CWCompFindIncludeFile(status->cpb, includeFileName, true, &hand, &size,
  246.                                         &includeSpec, &alreadyincluded, false);
  247.             if (err != noErr)
  248.             {
  249.                 CWCompOSErrorMessage(status->cpb, "The include file could not be found.", err);
  250.             }
  251.             else
  252.             {
  253.                 short incNameLength;
  254.                 Handle incName;
  255.                 
  256.                 if (hand != NULL)
  257.                 {
  258.                     // XXX -- file is open in IDE window -- use temp file eventually
  259.                     CWCompErrorMessage(status->cpb, "The include file is open. Please close it first.");
  260.                     err = paramErr;
  261.                 }
  262.                 else
  263.                 {
  264.                     err = FSpGetFullPath(&includeSpec, &incNameLength, &incName);
  265.                     if (err != noErr)
  266.                     {
  267.                         CWCompOSErrorMessage(status->cpb, "Error getting full path name from include file.", err);
  268.                     }
  269.                     else
  270.                     {
  271.                         PtrAndHand("Execute \'", commandHandle, sizeof("Execute \'") - 1);
  272.                         HandAndHand(incName, commandHandle);
  273.                         PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  274.                         DisposeHandle(incName);
  275.                     }
  276.                 }
  277.             }
  278.         }
  279.  
  280.         // add the template command line from prefs
  281.         if (err == noErr)
  282.         {
  283.             Byte state = HGetState((Handle)prefs);
  284.             HLock((Handle)prefs);
  285.             PtrAndHand((*prefs)->extensions[currentExtension].commandTemplate + 1, commandHandle,
  286.                         (*prefs)->extensions[currentExtension].commandTemplate[0]);
  287.             HSetState((Handle)prefs, state);
  288.         }
  289.  
  290.         // make the ToolServer command        
  291.         if (err == noErr)
  292.         {
  293.             HLock(commandHandle);
  294.             command.descriptorType = typeNull;
  295.             command.dataHandle = NULL;
  296.             err = AECreateList(NULL, 0, false, &command);
  297.             if (err == noErr)
  298.                 err = AEPutPtr(&command, 0, typeChar, *commandHandle, GetHandleSize(commandHandle));
  299.         }
  300.         DisposeHandle(commandHandle);
  301.         
  302.         if (err == noErr)
  303.         {
  304.             // XXX create a progress indicator window
  305.     
  306.             // send the ToolServer command -- XXX with progress indicator idleProc
  307.             err = ToolServerCommand(&command, &output, &diagnostic, NULL, NULL);
  308.             AEDisposeDesc(&command);
  309.     
  310.             // XXX remove the progress indicator
  311.  
  312.             // show number of lines processed
  313.             CWCompDisplayLines(status->cpb, status->linecount);
  314.  
  315.             // display any diagnostic result
  316.             if (err != noErr)
  317.             {
  318.                 if (diagnostic != NULL)
  319.                 {
  320.                     char null = 0;
  321.                     PtrAndHand(&null, (Handle)diagnostic, 1);
  322.                     HLock((Handle)diagnostic);
  323.                     CWCompErrorMessage(status->cpb, (const char*)*diagnostic);
  324.                 }
  325.                 else
  326.                 {
  327.                     CWCompOSErrorMessage(status->cpb, "ToolServer error. ", err);
  328.                 }
  329.             }
  330. #if 0
  331.             else
  332.             {
  333.                 // XXX test code for a future version
  334.                 FSSpec testSpec;
  335.                 unsigned long time;
  336.                 Handle path;
  337.                 short len;
  338.                 char c;
  339.                 
  340.                 testSpec.vRefNum = status->cpb->targetfile.vRefNum;
  341.                 testSpec.parID = status->cpb->targetfile.parID;
  342.                 BlockMoveData(nameStem, testSpec.name, nameStem[0] + 1);
  343.                 BlockMoveData(".xh", testSpec.name + nameStem[0] + 1, 3);
  344.                 testSpec.name[0] += 3;
  345.                 err = FSpGetFullPath(&testSpec, &len, &path);
  346.                 if (err != noErr) DebugStr("\pgoldarnit!");
  347.                 c = 0;
  348.                 PtrAndHand(&c, path, 1);
  349.                 HLock(path);
  350.                 err = CWCompGetPrecompiledHeaderSpec(status->cpb, &testSpec, (char*)*path);
  351.                 if (err != noErr) DebugStr("\pfug!");
  352.                 GetDateTime(&time);
  353.                 CWCompSetModDate(status->cpb, &testSpec, time);
  354.                 //if (err != noErr) DebugStr("\pheck!");
  355.             }
  356. #endif
  357.         }
  358.         if (output != NULL) DisposeHandle((Handle)output);
  359.         if (diagnostic != NULL) DisposeHandle((Handle)diagnostic);
  360.     }
  361.     
  362.     return err;
  363. }
  364.  
  365.  
  366. static OSErr    ProcessFile(ToolFrontEndStatus* status, ToolFrontEndPref** prefs,
  367.                             short currentExtension)
  368. {
  369.     OSErr err;
  370.     FCBPBRec pb;
  371.     FSSpec spec;
  372.     CInfoPBRec ci;
  373. #if GENERATINGCFM
  374.     long response;
  375. #endif
  376.     
  377.     // find the scanner folder and file
  378.     pb.ioFCBIndx = 0; // use ioRefNum
  379.     pb.ioRefNum = LMGetCurApRefNum();
  380.     pb.ioNamePtr = NULL;
  381.     err = PBGetFCBInfoSync(&pb);
  382.     if (err != noErr) return err;
  383.     GetIndString(spec.name, 129, 1); // CodeWarrior Plugins
  384.     ci.dirInfo.ioNamePtr = spec.name;
  385.     ci.dirInfo.ioVRefNum = pb.ioFCBVRefNum;
  386.     ci.dirInfo.ioDrDirID = pb.ioFCBParID;
  387.     ci.dirInfo.ioFDirIndex = 0;
  388.     err = PBGetCatInfoSync(&ci);
  389.     if (err != noErr) return err;
  390.     GetIndString(spec.name, 129, 2); // Include Scanners
  391.     ci.dirInfo.ioNamePtr = spec.name;
  392.     ci.dirInfo.ioVRefNum = pb.ioFCBVRefNum;
  393.     ci.dirInfo.ioDrDirID = ci.dirInfo.ioDrDirID;
  394.     ci.dirInfo.ioFDirIndex = 0;
  395.     err = PBGetCatInfoSync(&ci);
  396.     if (err != noErr) return err;
  397.     spec.vRefNum = pb.ioFCBVRefNum;
  398.     spec.parID = ci.dirInfo.ioDrDirID;
  399.     BlockMoveData((*prefs)->extensions[currentExtension].scanner, spec.name,
  400.                     (*prefs)->extensions[currentExtension].scanner[0] + 1);
  401.  
  402. #if GENERATINGCFM
  403.     // if on PowerPC...
  404.     err = Gestalt(gestaltSysArchitecture, &response);
  405.     if (err == noErr && response == gestaltPowerPC)
  406.     {
  407.         // load code fragment
  408.         CFragConnectionID connID;
  409.         Str255 errName;
  410.         UniversalProcPtr newRoutine = 0;
  411.         Ptr mainAddr;
  412.  
  413.         err = GetDiskFragment(&spec, 0, kWholeFork, NULL, kLoadNewCopy, &connID, &mainAddr,
  414.                                 errName);
  415.         if (err != noErr) return err;
  416.         
  417.         // call main entry point
  418.         newRoutine = NewRoutineDescriptor((ProcPtr)mainAddr, uppScannerEntryPointInfo, GetCurrentArchitecture());
  419.         if (newRoutine == NULL)
  420.         {
  421.             err = MemError();
  422.             CloseConnection(&connID);
  423.             return err;
  424.         }
  425.         err = CallUniversalProc(newRoutine, uppScannerEntryPointInfo, status);
  426.         
  427.         // unload code fragment
  428.         CloseConnection(&connID);
  429.     }
  430.     else // 68K
  431. #endif
  432.     {
  433.         Handle h;
  434.         pascal OSErr (*f)(ToolFrontEndStatus* status);
  435.         short refNum;
  436.         
  437.         // open resource file
  438.         refNum = FSpOpenResFile(&spec, fsRdPerm);
  439.         if (refNum < 0) return ResError();
  440.         
  441.         // load code resource
  442.         h = Get1Resource('Scan', 128);
  443.         if (h == 0)
  444.         {
  445.             CloseResFile(refNum);
  446.             return resNotFound;
  447.         }
  448.         
  449.         // call main entry point
  450.         HNoPurge(h);
  451.         HLock(h);
  452.         f = (pascal OSErr (*)(ToolFrontEndStatus* status))(*h);
  453.         err = (*f)(status);
  454.         
  455.         // close resource file
  456.         CloseResFile(refNum);
  457.     }
  458.     
  459.     if (err != noErr)
  460.     {
  461.         Str31 s;
  462.         NumToString(err, s);
  463.         p2cstr(s);
  464.         CWCompErrorMessage(status->cpb, (char*)s);
  465.     }
  466.     
  467.     return err;
  468. }
  469.